package pri.zxx.word.dat;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import pri.zxx.learndemo.exceptionhandle.CustomException;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.IntStream;

@Slf4j
public abstract class AbstractPoiWordTemplate<T extends AbstractWordData> {

    protected XWPFDocument xwpfDocument;

    /**
     * 初始化文件
     */
    public AbstractPoiWordTemplate() {

        this.xwpfDocument = new XWPFDocument();
        pageSz_Mrg(xwpfDocument, 11907, 16840, 1800, 1440,860,500);
        defaultFonts(xwpfDocument, "仿宋", "Times New Roman", "仿宋");
    }

    /**
     * 自定义样式
     */
    public abstract AbstractPoiWordTemplate<T> customStyle(T abstractWordData);

    /**
     * 自定义页眉 页脚
     */
    public abstract AbstractPoiWordTemplate<T> headerFooter(T abstractWordData);

    /**
     * 页面内容
     */
    public abstract AbstractPoiWordTemplate<T> buildContext(T abstractWordData);

    public void out(String filePath) {

        Path path = Paths.get(filePath);
        OutputStream outputStream;
        try {
            Files.deleteIfExists(path);
            outputStream = Files.newOutputStream(path);
            xwpfDocument.write(outputStream);
        } catch (IOException e) {
            log.error("生成临时文件异常：{}", filePath);
            throw new CustomException(1, "生成临时文件异常：" + filePath);
        } finally {
            try {
                xwpfDocument.close();
            } catch (IOException e) {
                log.error("关闭输出流异常", e);
            }
        }
    }


    public static void pageSz_Mrg(XWPFDocument xwpfDocument, long pgW, long pgH, long mrgLR, long mrgTB, long h, long f) {
        pageSz_Mrg(xwpfDocument, pgW, pgH, mrgLR, mrgLR, mrgTB, mrgTB, h, f);
    }

    public static void pageSz_Mrg(XWPFDocument xwpfDocument, long pgW, long pgH, long mrgLR, long mrgTB, long hf) {
        pageSz_Mrg(xwpfDocument, pgW, pgH, mrgLR, mrgLR, mrgTB, mrgTB, hf,hf);
    }

    public static void pageSz_Mrg(XWPFDocument xwpfDocument, long pgW, long pgH, long mrgL, long mrgR, long mrgT, long mrgB, long header, long footer) {
        CTBody body = xwpfDocument.getDocument().getBody();
        CTSectPr sectPr = body.addNewSectPr();
        CTPageSz pgsz = sectPr.isSetPgSz() ? sectPr.getPgSz() : sectPr.addNewPgSz();
        pgsz.setW(BigInteger.valueOf(pgW));
        pgsz.setH(BigInteger.valueOf(pgH));
        pgsz.setOrient(STPageOrientation.LANDSCAPE);
        CTPageMar ctPageMar = sectPr.addNewPgMar();
        ctPageMar.setLeft(BigInteger.valueOf(mrgL));
        ctPageMar.setRight(BigInteger.valueOf(mrgR));
        ctPageMar.setTop(BigInteger.valueOf(mrgT));
        ctPageMar.setBottom(BigInteger.valueOf(mrgB));
        ctPageMar.setHeader(BigInteger.valueOf(header));
        ctPageMar.setFooter(BigInteger.valueOf(footer));
    }

    public static void defaultFonts(XWPFDocument xwpfDocument, String chinese, String ascii, String hansi) {
        XWPFStyles styles = xwpfDocument.createStyles();
        CTFonts fonts = CTFonts.Factory.newInstance();
        fonts.setEastAsia(chinese);
        fonts.setAscii(ascii);
        fonts.setHAnsi(hansi);
        styles.setDefaultFonts(fonts);
    }


    public static XWPFRun pTextPound(XWPFParagraph paragraph, String text, boolean bold, int fontSize) {
        XWPFRun pr = paragraph.createRun();
        pr.setText(text);
        pr.setBold(bold);
        CTRPr ctrPr = pr.getCTR().addNewRPr();
//        传入的值是磅数 * 2
        ctrPr.addNewSzCs().setVal(BigInteger.valueOf(fontSize));
        ctrPr.addNewSz().setVal(BigInteger.valueOf(fontSize));
        return pr;
    }

    public static XWPFRun pText(XWPFParagraph paragraph, String text, boolean bold, int fontSize) {
        XWPFRun pr = paragraph.createRun();
        pr.setText(text);
        pr.setBold(bold);
        pr.setFontSize(fontSize);
        return pr;
    }

    public static XWPFRun pTextBreak(XWPFParagraph paragraph, String text, boolean bold, int fontSize) {
        XWPFRun pr = paragraph.createRun();
        pr.setText(text);
        pr.setBold(bold);
        pr.setFontSize(fontSize);
        pr.addBreak(BreakType.PAGE);
        return pr;
    }

    public static void pText(XWPFParagraph paragraph, String text, boolean bold, int fontSize, int returnCount) {
        XWPFRun pr = paragraph.createRun();
        pr.setText(text);
        pr.setBold(bold);
        pr.setFontSize(fontSize);
        if (returnCount > 0) {
            IntStream.range(0, returnCount).forEach(value -> pr.addCarriageReturn());
        }
    }

    /**
     * 创建 r:1 c:1 的表格
     */
    public static XWPFTable createTable(XWPFDocument xwpfDocument, int widthPercentage, TableRowAlign rowAlign) {
        XWPFTable table = xwpfDocument.createTable();
        table.setWidth(widthPercentage + "%");
        table.setTableAlignment(rowAlign);
        return table;
    }

    /**
     * 创建 r c 的表格
     */
    public static XWPFTable createTable(XWPFDocument xwpfDocument, int row, int col, int widthPercentage, TableRowAlign rowAlign) {
        XWPFTable table = xwpfDocument.createTable(row, col);
        table.setWidth(widthPercentage + "%");
        table.setTableAlignment(rowAlign);
        return table;
    }


    /**
     * @Description: 跨列合并
     * table要合并单元格的表格
     * row要合并哪一行的单元格
     * fromCell开始合并的单元格
     * toCell合并到哪一个单元格
     */
    public void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
        for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
            if (cellIndex == fromCell) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    /**
     * @Description: 跨行合并
     * table要合并单元格的表格
     * col要合并哪一列的单元格
     * fromRow从哪一行开始合并单元格
     * toRow合并到哪一个行
     */
    public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            if (rowIndex == fromRow) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
            }
        }
    }
}
